home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / Apps / ScreenSavers / BackSpaceViews / SpewView.BackModule / SpewView.m < prev    next >
Encoding:
Text File  |  1995-06-12  |  6.8 KB  |  255 lines

  1. /* $Id$ */
  2.  
  3. // SpewView is written by Pedja Bogdanovich
  4. // Permission is granted to freely use and distribute this software
  5. // provided this notice is left attached and no monetary gain is made.
  6.  
  7. #import "SpewView.h"
  8. #import "Thinker.h"
  9.  
  10. #define TEXTTIMEDEFAULT "Spew TextTime"
  11. #define SLEEPTIMEDEFAULT "Spew SleepTime"
  12.  
  13. #define MINWIDTHRAT .2
  14. #define MAXWIDTHRAT .75
  15. #define MINCHARS 12
  16. #define MAXFONTRAT .075
  17. #define MINFONTRAT .025
  18. #define MINFONTSIZE 12
  19.  
  20. #define exp2(x) pow(2,x)
  21. #define rnd() ((random()&0xffffff)/(float)0xffffff)
  22.  
  23. static const char *fontlist[]={
  24.   "Courier", "Courier-Oblique", "Courier-Bold", "Courier-BoldOblique",
  25.   "Helvetica", "Helvetica-Oblique", "Helvetica-Bold", "Helvetica-BoldOblique",
  26.   "Times-Roman", "Times-Italic", "Times-Bold", "Times-BoldItalic"
  27.   // Add more fonts here...
  28.   };
  29.  
  30. static int pointsize[]={
  31.   14,18,24,32,36,48,56,64
  32.   // Add more font-sizes here...
  33.   };
  34.  
  35. static NXColor pickColor()
  36. {
  37.   int i;
  38.   float r, g, b;
  39.   switch([Window defaultDepthLimit]) {
  40.   case NX_TwoBitGrayDepth:
  41.     return NXConvertGrayToColor(1.-(random()%2)/3.);
  42.   case NX_EightBitGrayDepth:
  43.     return NXConvertGrayToColor(1.-(random()%128)/256.);
  44.   case NX_TwelveBitRGBDepth:
  45.   case NX_TwentyFourBitRGBDepth:
  46.   default:
  47.     i=random()%4096;
  48.     r=fmod(i,16)/16;
  49.     g=fmod(i-r,256)/256;
  50.     b=(i-fmod(i,256))/4096;
  51.     r=.2+r*.8; g=.2+g*.8; b=.2+b*.8; /* Not too dark. */
  52.     return NXConvertRGBToColor(r,g,b);
  53.   }
  54. }
  55.  
  56. // fontsizes can be made font specific...
  57. static float pickFontSize(float fmin, float fmax)
  58. {
  59.   int i, j=sizeof(pointsize)/sizeof(int);
  60.   int imin=j-1, imax=0;
  61.   for(i=0;i<j;i++) if(pointsize[i]>=fmin) { imin=i; break; }
  62.   for(i=0;i<j;i++) if(pointsize[i]<=fmax) imax=i;
  63.   if(imin>=imax) i=imin;
  64.   else i=imin+random()%(imax-imin+1);
  65.   return pointsize[i];
  66. }
  67.  
  68. static Font *pickFont(float sz)
  69. {
  70.   return [Font newFont:fontlist[random()%(sizeof(fontlist)/sizeof(char*))]
  71.          size:sz /* matrix:NX_IDENTITYMATRIX*/];
  72. }
  73.  
  74. @implementation SpewView
  75. + initialize
  76. {
  77.   static NXDefaultsVector spewDefaults={
  78.     {TEXTTIMEDEFAULT,"12"},
  79.     {SLEEPTIMEDEFAULT,"2"},
  80.     {NULL}};
  81.   NXRegisterDefaults([NXApp appName],spewDefaults);
  82.   return [super initialize];
  83. }
  84.  
  85. - initFrame:(const NXRect *)fr
  86. {
  87.   NXSize sz={1e6,1e6};
  88.  
  89.   [super initFrame:fr];
  90.   textOnScreen=NO;
  91.  
  92.   textView=[[Text alloc] initFrame:NULL];
  93. //  [textView setRetainedWhileDrawing:NO];
  94.   [textView setVertResizable:YES];
  95.   [[textView setHorizResizable:NO] setHorizResizable:NO];
  96.   [[textView setSelectable:YES] setEditable:NO];
  97.   [textView setMonoFont:YES];
  98.   [textView setBackgroundGray:NX_BLACK];
  99.   [textView setMaxSize:&sz];
  100.  
  101.   defaultTextTime=atoi(NXGetDefaultValue([NXApp appName],TEXTTIMEDEFAULT));
  102.   defaultSleepTime=atoi(NXGetDefaultValue([NXApp appName],SLEEPTIMEDEFAULT));
  103.   srandom(time(0));
  104.   return self;
  105. }
  106.  
  107. // spewAgain method will load new spew text into textView.
  108. // textView's text content, font, color, and frame are set.
  109. - spewAgain
  110. {
  111.   char buf[200];
  112.   char tmpfile[100];
  113.   FILE *f;
  114.   NXRect r;
  115.   static const int alignment[]={NX_LEFTALIGNED,NX_RIGHTALIGNED,NX_CENTERED};
  116.  
  117.   sprintf(tmpfile,"/tmp/.#tmp_spew%08x",getpid());
  118.   sprintf(buf,"sh -c 'cd %s; spew >%s'",
  119.       [(BSThinker()) moduleDirectory:"Spew"],
  120.       tmpfile);
  121.   system(buf);
  122.  
  123.   if(f=fopen(tmpfile,"r")) {
  124.     struct stat statbuf;
  125.     char *spewtext;
  126.     float w, h, x, y;
  127.  
  128.     fstat(fileno(f),&statbuf);
  129.     spewtext=alloca(statbuf.st_size+1);
  130.     fread(spewtext,1,statbuf.st_size,f); spewtext[statbuf.st_size]=0;
  131.     fclose(f);
  132.  
  133.     // Random selections below don't work very well for small windows...
  134.  
  135.     // set color
  136.     [textView setTextColor:pickColor()];
  137.  
  138.     // set font
  139.     h=pickFontSize(MAX(MINFONTSIZE,NX_HEIGHT(&bounds)*MINFONTRAT), /* min */
  140.            NX_HEIGHT(&bounds)*MAXFONTRAT); /* max font size */
  141.     [textView setFont:pickFont(h)];
  142.  
  143.     // set width
  144.     w=MAX(NX_WIDTH(&bounds)*MINWIDTHRAT,MINCHARS*[[textView font] pointSize]);
  145.     x=NX_WIDTH(&bounds)*MAXWIDTHRAT;
  146.     if(w<x) w+=(x-w)*rnd();
  147.     [textView sizeTo:w :50];
  148.  
  149.     // set content
  150.     [textView setSel:0 :[textView textLength]];
  151.     [textView replaceSel:spewtext];
  152.  
  153.     // set alignment
  154.     [textView setAlignment:alignment[random()%(sizeof(alignment)/sizeof(int))]];
  155.  
  156.     // set position; height is calculated by the text object
  157.     [textView getFrame:&r];
  158.     w=NX_WIDTH(&r); h=NX_HEIGHT(&r);
  159.     x=NX_X(&bounds)+(NX_WIDTH(&bounds)-w)*rnd();
  160.     y=NX_Y(&bounds)+(NX_HEIGHT(&bounds)-h)*rnd();
  161.     [textView moveTo:x :y];
  162.   }  
  163.   unlink(tmpfile);
  164.   return self;
  165. }
  166.  
  167. - drawSelf:(NXRect *)rects :(int)rectCount
  168. {
  169.   if(rects==NULL || rectCount==0) return self;
  170.   PSsetgray(NX_BLACK); NXRectFill(rects);
  171.   return self;
  172. }
  173.  
  174. - inspector:sender
  175. {
  176.   char buf[MAXPATHLEN];
  177.     
  178.   if(!sharedInspectorPanel) {
  179.     sprintf(buf,"%s/Spew.nib",[sender moduleDirectory:"Spew"]);
  180.     [NXApp loadNibFile:buf owner:self withNames:NO];
  181.  
  182.     // load default values into inspector
  183.     [textTimeField setIntValue:defaultTextTime];
  184.     [textTimeField sendAction:[textTimeField action] to:[textTimeField target]];
  185.     [sleepTimeField setIntValue:defaultSleepTime];
  186.     [sleepTimeField sendAction:[sleepTimeField action] to:[sleepTimeField target]];
  187.   }
  188.   return sharedInspectorPanel;
  189. }
  190.  
  191. // This method is stolen from BackView
  192. - (BOOL)timePassed:(BStimeval)delay
  193. {
  194.   BStimeval now, msec;
  195.   BOOL result;
  196.     
  197.   now=currentTimeInMs();
  198.   if(SVthen==0) SVthen=now;    /* added by shou-h@nexus.or.jp */
  199.   msec=now-SVthen;
  200.  
  201.   /* so as not to suck too many cycles, if I'm waiting for some
  202.      time more than a tenth of a second in the future, I sleep
  203.      a while.  This interval is short enough that the app shouldn't
  204.      seem unresponsive to user actions.
  205.     
  206.      ok, so you'd never pull this trick if the user had to type.
  207.      A better solution would be to coordinate the timed entry better,
  208.      but I get slightly better performance from spinning in my
  209.      timed entry (a bad idea for most apps...) */
  210.     
  211.   if((msec+120)<delay) {
  212.     usleep(110000);
  213.     return NO;
  214.   }
  215.     
  216.   result=(msec>delay);
  217.   if(result) SVthen=now;
  218.  
  219.   return result;
  220. }
  221.  
  222.  
  223. - oneStep
  224. {
  225.   int t; char buf[12];
  226.  
  227.   if(sharedInspectorPanel) {
  228.     t=[textTimeField intValue];
  229.     if(t!=defaultTextTime) {    /* update default texttime if needed */
  230.       sprintf(buf,"%d",t); defaultTextTime=t;
  231.       NXWriteDefault([NXApp appName],TEXTTIMEDEFAULT,buf);
  232.     }
  233.     t=[sleepTimeField intValue];
  234.     if(t!=defaultSleepTime) {    /* update default sleeptime if needed */
  235.       sprintf(buf,"%d",t); defaultSleepTime=t;
  236.       NXWriteDefault([NXApp appName],SLEEPTIMEDEFAULT,buf);
  237.     }
  238.   }    
  239.  
  240.   if(textOnScreen) {
  241.     if(![self timePassed:defaultTextTime*1000]) return self;
  242.     [textView removeFromSuperview];
  243.   } else {
  244.     if(![self timePassed:defaultSleepTime*1000]) return self;
  245.     [self spewAgain];
  246.     [self addSubview:textView];
  247.     [window makeFirstResponder:textView];
  248.   }
  249.   textOnScreen=!textOnScreen;
  250.   [self display];
  251.   return self;
  252. }
  253. @end
  254.  
  255. /* EOF */